package com.share.order.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

/**
 * 死信队列配置类
 * 用于配置死信交换机、队列及它们之间的绑定关系
 * 实现消息过期后自动转发到死信队列的功能
 */
@Slf4j
@Configuration
public class DeadLetterMqConfig {

    // 死信交换机名称
    public static final String exchange_dead = "exchange.dead";
    // 死信路由键1 - 用于正常队列绑定
    public static final String routing_dead_1 = "routing.dead.1";
    // 死信路由键2 - 用于死信队列绑定
    public static final String routing_dead_2 = "routing.dead.2";
    // 普通队列名称（会产生死信的队列）
    public static final String queue_dead_1 = "queue.dead.1";
    // 死信队列名称（接收死信的队列）
    public static final String queue_dead_2 = "queue.dead.2";

    /**
     * 声明死信交换机
     * Direct类型交换机，根据路由键精确匹配
     *
     * @return 死信交换机实例
     */
    @Bean
    public DirectExchange exchange() {
        log.info("创建死信交换机: {}", exchange_dead);
        // 参数说明：交换机名称、是否持久化、是否自动删除、附加参数
        return new DirectExchange(exchange_dead, true, false, null);
    }

    /**
     * 普通队列（会产生死信的队列）
     * 配置了死信相关参数，消息过期后会转发到死信队列
     *
     * @return 普通队列实例
     */
    @Bean
    public Queue queue1() {
        // 设置队列的附加参数
        HashMap<String, Object> map = new HashMap<>();
        // 设置死信交换机 - 消息成为死信后将被发送到的交换机
        map.put("x-dead-letter-exchange", exchange_dead);
        // 设置死信路由键 - 消息成为死信后用于转发的路由键
        map.put("x-dead-letter-routing-key", routing_dead_2);
        // 设置消息过期时间 - 10秒后消息自动过期成为死信
        map.put("x-message-ttl", 10 * 1000);

        log.info("创建普通队列: {}，并配置死信参数", queue_dead_1);
        // 参数说明：队列名称、是否持久化、是否排他、是否自动删除、附加参数
        return new Queue(queue_dead_1, true, false, false, map);
    }

    /**
     * 普通队列与死信交换机的绑定
     *
     * @return 绑定关系实例
     */
    @Bean
    public Binding binding() {
        log.info("将队列 {} 通过路由键 {} 绑定到交换机 {}", queue_dead_1, routing_dead_1, exchange_dead);
        // 将普通队列通过routing_dead_1路由键绑定到死信交换机
        return BindingBuilder.bind(queue1()).to(exchange()).with(routing_dead_1);
    }

    /**
     * 死信队列（专门接收死信的队列）
     * 这是一个普通队列，用于接收从queue_dead_1转发来的死信消息
     *
     * @return 死信队列实例
     */
    @Bean
    public Queue queue2() {
        log.info("创建死信队列: {}", queue_dead_2);
        // 参数说明：队列名称、是否持久化、是否排他、是否自动删除、附加参数
        return new Queue(queue_dead_2, true, false, false, null);
    }

    /**
     * 死信队列与死信交换机的绑定
     *
     * @return 绑定关系实例
     */
    @Bean
    public Binding binding2() {
        log.info("将队列 {} 通过路由键 {} 绑定到交换机 {}", queue_dead_2, routing_dead_2, exchange_dead);
        // 将死信队列通过routing_dead_2路由键绑定到死信交换机
        return BindingBuilder.bind(queue2()).to(exchange()).with(routing_dead_2);
    }
}
